#pragma once
#include"Runtime/BattleFirePrefix.h"
#include "Runtime/Base/Object.h"
namespace BattleFire {
	enum ColorBufferMask {
		kColorBufferMaskR,
		kColorBufferMaskG,
		kColorBufferMaskB,
		kColorBufferMaskA,
		kColorBufferMaskCount
	};
	enum LogicOperation {
		kLogicOperationClear,
		kLogicOperationAnd,
		kLogicOperationAndReverse,
		kLogicOperationCopy,
		kLogicOperationAndInverted,
		kLogicOperationNoOperation,
		kLogicOperationXor,
		kLogicOperationOr,
		kLogicOperationNor,
		kLogicOperationEquivalent,
		kLogicOperationInvert,
		kLogicOperationOrReverse,
		kLogicOperationCopyInverted,
		kLogicOperationOrInverted,
		kLogicOperationNand,
		kLogicOperationSet
	};
	enum UniformInputAccessShaderStage {
		kUniformInputAccessShaderStageVertex = 1,
		kUniformInputAccessShaderStageTessellationControl = 2,
		kUniformInputAccessShaderStageTessellationEvaluation = 4,
		kUniformInputAccessShaderStageGeometry = 8,
		kUniformInputAccessShaderStageFragment = 16,
		kUniformInputAccessShaderStageCompute = 32
	};
	enum class ShaderStage {
		kShaderStageVertex,
		kShaderStageTessellationControl,
		kShaderStageTessellationEvaluation,
		kShaderStageGeometry,
		kShaderStageFragment,
		kShaderStageCompute,
		kShaderStageCount
	};
	enum class BufferUsage {
		kBufferUsageCPUReadWrite,
		kBufferUsageCPUAndGPUReadWrite,
		kBufferUsageCPUWriteGPURead
	};
	class LShaderCode : public ReferencedObject {
	public:
		const char* mCode;
		int mCodeLen;
		bool mbSharedCode;
		char mShaderPath[256];
		LShaderCode(const char* shaderPath,const char* code,int len, bool shared = false) :
			mCode(code),mCodeLen(len),mbSharedCode(shared) {
			memset(mShaderPath, 0, 256);
			strcpy(mShaderPath, shaderPath);
		}
		~LShaderCode() {
			if (!mbSharedCode){
				delete[] mCode;
			}
		}
	};
	class RenderResource {
	public:
		virtual BattleFireUInt32 GetResource()=0;
	};
	class CBuffer : public RenderResource {
	public:
		CBuffer():mBufferName(0){}
		BattleFireUInt32 mBufferName;
		BattleFireUInt32 GetResource()
		{
			return mBufferName;
		}
	};
	class CShader:public RenderResource
	{
		CShader():mBufferName(0){}
		BattleFireUInt32 mBufferName;
		BattleFireUInt32 GetResource()
		{
			return mBufferName;
		}
	};
	class LShaderPipeline : public ReferencedObject {
	public:
		LShaderPipeline(const char * shaderPipelineName) {
			mShaderStages[(int)ShaderStage::kShaderStageVertex] = nullptr;
			mShaderStages[(int)ShaderStage::kShaderStageTessellationControl] = nullptr;
			mShaderStages[(int)ShaderStage::kShaderStageTessellationEvaluation] = nullptr;
			mShaderStages[(int)ShaderStage::kShaderStageGeometry] = nullptr;
			mShaderStages[(int)ShaderStage::kShaderStageFragment] = nullptr;
			mShaderStages[(int)ShaderStage::kShaderStageCompute] = nullptr;
			memset(mShaderPipelineName, 0, 256);
			strcpy(mShaderPipelineName, shaderPipelineName);
		};
		virtual ~LShaderPipeline();
		virtual void Initialize(const CShader* vs = nullptr, const CShader* gs = nullptr, const CShader* fs = nullptr, const CShader* cs = nullptr);
		const CShader* mShaderStages[(int)ShaderStage::kShaderStageCount];
		char mShaderPipelineName[256];
	public:
		static std::unordered_map<std::string, LShaderPipeline*> mCachedShaderPipelines;
		static LShaderPipeline* GetCachedShaderPipeline(const char* shaderPipelineName);
	public:
		virtual void Active() const {}
		virtual void Deactive() const {}
		virtual void InitShaderPipeline() {}
	};
	class LBuffer {
	public:
		LBuffer(BattleFireSInt32 inElementSize = 0,BattleFireSInt32 inElementCount=0);
		virtual ~LBuffer();
		BattleFireSInt32 mPerElementSize;
		BattleFireSInt32 mTotalElementCount;
		BattleFireSInt32 mBufferSize;
		BattleFireAny mData;
	};
	class RBuffer {
	public:
		RBuffer(LBuffer*inLBuffer,BufferUsage inBufferUsage = BufferUsage::kBufferUsageCPUReadWrite):mBufferUsage(inBufferUsage){}
		BufferUsage mBufferUsage;
	};
	class CGI {
	public:
		virtual bool Initialize(HDC inHDC,int inViewWidth,int inViewHeight) = 0;
	public:
		virtual RenderResource* CreateVertexBuffer(BattleFireAny* inLBufferData, int inPerVertexDataSizeInBytes, int inCountInBytes,BufferUsage inBufferUsage)=0;
		virtual RenderResource* CreateIndexBuffer(BattleFireAny* inLBufferData, int inPerElementSizeInBytes, int inCountInBytes, BufferUsage inBufferUsage)=0;
		virtual RenderResource* CreateShader(ShaderStage shaderStage, const char* shaderUserPath, const char* shaderSourceCode,int shaderCodeLen,bool shared=false)=0;
		virtual RenderResource* CreateShaderPipeline(LShaderPipeline* shaderPipeline)=0;
		static std::unordered_map<std::string, LShaderPipeline*> mCachedShaderPipelines;
	public:
		static bool mbSupportHalfFloatColorBuffer;
		static bool mbSupportFloatColorBuffer;
		static bool mbSupportHalfFloatVertex;
		static bool mbSupportComputeShader;
		static int mMaxVertexShaderSSBOCount;
		static int mMaxTessellaionControlShaderSSBOCount;
		static int mMaxTessellaionEvaluationShaderSSBOCount;
		static int mMaxGeometryShaderSSBOCount;
		static int mMaxFragmentShaderSSBOCount;
		static int mMaxComputeShaderSSBOCount;
		static int mMaxCombinedShaderSSBOCount;
		static CGI* sDynamicCGI;
	};
}